#pragma once

#include <d3d9.h>
#include <tchar.h>
#include <vector>
#include <map>
#include "GameCommands.h"
#include "WindowMessagesProcessor.h"
#include "RenderingManager.h"
#include "MeshStorage.h"


class IRenderableObject;
class IMesh;
class CTimer;
class CGraphicsController;
class CD3DInitializer;
class IMovable;
class CTerrainMesh;
class ActionObject;
class GameStateController;
class CInputController;
class AnimatedImage;

class CGameApp : public IGameCommands, public IWindowMessagesProcessor, public IRenderingManager, public IMeshStorage
{
private:
   HINSTANCE m_hInstance;
   HWND m_hWnd;

   IDirect3D9* m_d3d9;

   CD3DInitializer* m_d3dInitializer;
   CGraphicsController* m_graphicsController;
   CInputController* m_inputController;
   GameStateController* m_gameStateController;
   CTimer* m_timer;

   std::map<std::string, IMesh*> m_mesh;
   std::map<std::string, AnimatedImage*> m_image;
   std::map<std::string, CTerrainMesh*> m_terrain;
   std::vector<IRenderableObject*> m_renderableObjects;
   
public:
	CGameApp(HINSTANCE m_hInstance, int nCmdShow);
	~CGameApp(void);

   void beginGame(void);

   void closeApp(void);

   LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

   void startRendering(IRenderableObject& renderable);

   void stopRendering(IRenderableObject& renderable);

   void clearRenderingList() {m_renderableObjects.clear();}

   IScenery& getTerrainScenery(const std::string& trackName);

   IRenderableObject& getTerrainRenderable(const std::string& trackName);

   IMesh& getLaserMesh() {return *(m_mesh["laser"]);}

   IMesh& getCarMesh() {return *(m_mesh["car"]);}

   IMesh& getPoleMesh() {return *(m_mesh["pole"]);}

   AnimatedImage& getPolePositionLight() {return *(m_image["polePositionLight"]);}

   AnimatedImage& getIntroScreen() {return *(m_image["introScreen"]);}

   AnimatedImage& getMainMenuScreen() {return *(m_image["mainMenuScreen"]);}

   AnimatedImage& getSelectionHighlight() {return *(m_image["selectionHighlight"]);}

   AnimatedImage& getVictoryScreen() {return *(m_image["victory"]);}

   AnimatedImage& getDefeatScreen() {return *(m_image["defeat"]);}

private:
   bool initInstance(bool windowedMode, unsigned int width, unsigned int height, int nCmdShow);
  
   void buildScene(void);

   void advanceGameState(void);
};
